package com.lanyou.esb.cook.proxy.redis;

import java.io.IOException;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.exceptions.JedisException;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.lanyou.esb.cook.proxy.common.Constants;
import com.lanyou.esb.cook.proxy.common.ParamFactory;
import com.lanyou.esb.cook.proxy.exception.ParamSetRuntimeException;
import com.lanyou.esb.cook.proxy.redis.vo.RedisSetting;

/**
 * Redis连接池管理工具
 * 
 * @author Davey.wu
 */
public class JedisPoolUtils {
	/** 连接池 **/
	private static JedisPool pool;

	/**
	 * 建立连接池 真实环境，一般把配置参数缺抽取出来。
	 * 
	 * @throws ParamSetRuntimeException
	 * 
	 */
	private static void createJedisPool() {
		ObjectMapper mapper = new ObjectMapper();
		String json = ParamFactory.getString(Constants.REDIS_SERVER);
		RedisSetting redisSetting = null;
		try {
			redisSetting = mapper.readValue(json, RedisSetting.class);
		} catch (IOException e) {
			throw new ParamSetRuntimeException(e.getMessage(), "0");
		}
		// 建立连接池配置参数
		JedisPoolConfig config = new JedisPoolConfig();
		// 设置最大空闲连接
		config.setMaxIdle(redisSetting.getMaxIdle());
		// 设置最小 空闲连接
		config.setMinIdle(redisSetting.getMinIdle());
		// 设置最大阻塞时间，记住是毫秒数milliseconds
		config.setMaxWaitMillis(redisSetting.getMaxWaitMillis());
		// 设置最大连接数
		config.setMaxTotal(redisSetting.getMaxTotal());
		// 获得一个jedis实例的时候是否检查连接可用性
		config.setTestOnBorrow(redisSetting.isTestOnBorrow());
		// 创建连接池
		pool = new JedisPool(config, redisSetting.getRedisIp(),
				redisSetting.getRedisPort());
	}

	/**
	 * 在多线程环境同步初始化
	 * 
	 * @throws ParamSetRuntimeException
	 */
	private static synchronized void poolInit() {
		if (pool == null)
			createJedisPool();
	}

	/**
	 * 获取一个jedis 对象
	 * 
	 * @return
	 */
	public static Jedis getJedis() {
		if (pool == null) {
			poolInit();
		}
		boolean isContinue = true;
		Jedis jedis = null;
		int count = 0;
		try {
			do {
				try {
					jedis = pool.getResource();
					isContinue = false;
				} catch (Exception e) {
					isContinue = true;
					try {
						Thread.sleep(100);
					} catch (InterruptedException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
					count++;
				}
				if (count > 3) {
					break;
				}
			} while (isContinue);
		} catch (Exception e) {
			throw e;
		}
		if (jedis == null) {
			throw new JedisException("获取不到Redis连接");
		}
		return jedis;
	}

	/**
	 * 获取一个jedis 对象
	 * 
	 * @param init
	 *            :是否尝试从数据库加载参数
	 * @return
	 */
	public static Jedis getJedis(boolean init) {
		if (pool == null && init) {
			poolInit();
		}
		boolean isContinue = true;
		Jedis jedis = null;
		int count = 0;
		try {
			do {
				try {
					jedis = pool.getResource();
					isContinue = false;
				} catch (Exception e) {
					isContinue = true;
					try {
						Thread.sleep(100);
					} catch (InterruptedException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
					count++;
				}
				if (count > 3) {
					break;
				}
			} while (isContinue);
		} catch (Exception e) {
			throw e;
		}
		if (jedis == null) {
			throw new JedisException("获取不到Redis连接");
		}
		return jedis;
	}

	/**
	 * 归还一个连接
	 * 
	 * @param jedis
	 */
	public static void returnRes(Jedis jedis, boolean broken) {
		try {
			if (broken) {
				pool.returnBrokenResource(jedis);
			} else {
				pool.returnResource(jedis);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 销毁资源
	 */
	public static void destroy() {
		if (pool == null) {
			return;
		}
		pool.close();
		pool.destroy();
		pool = null;
	}
}